<!DOCTYPE html><html lang="zh-CN,en,default"><head hexo-theme="https://github.com/volantis-x/hexo-theme-volantis/tree/4.3.1"><meta charset="utf-8"><meta http-equiv="x-dns-prefetch-control" content="on"><link rel="dns-prefetch" href="https://cdn.jsdelivr.net"><link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin><meta name="renderer" content="webkit"><meta name="force-rendering" content="webkit"><meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"><meta name="HandheldFriendly" content="True"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"><link rel="preload" href="/css/first.css" as="style"><title>Git学习笔记 - Tang&#39;s blog.</title><meta name="keywords" content="Git"><meta name="description" content="Git工具学习笔记。主要参考了廖雪峰老师的学习网站。"><link rel="alternate" href="/atom.xml" title="Tang's blog." type="application/atom+xml"><meta name="msapplication-TileColor" content="#ffffff"><meta name="msapplication-config" content="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/blog/favicon/browserconfig.xml"><meta name="theme-color" content="#ffffff"><link rel="apple-touch-icon" sizes="180x180" href="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/img/favicon/cf_1o_180x180.png"><link rel="icon" type="image/png" sizes="32x32" href="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/img/favicon/cf_1o_32x32.png"><link rel="icon" type="image/png" sizes="16x16" href="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/img/favicon/cf_1o_16x16.png"><link rel="manifest" href="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/img/favicon/manifest2.json"><link rel="mask-icon" href="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/img/favicon/cf_image2vector.svg" color="#5bbad5"><link rel="shortcut icon" href="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/img/favicon/32favicon32.ico"><link rel="stylesheet" href="/css/first.css"><link rel="stylesheet" href="/css/style.css" media="print" onload='this.media="all",this.onload=null'><noscript><link rel="stylesheet" href="/css/style.css"></noscript><script id="loadcss"></script><script>window.MSInputMethodContext&&document.documentMode&&document.write('<style>html{overflow-x: hidden !important;overflow-y: hidden !important;}.kill-ie{text-align:center;height: 100%;margin-top: 15%;margin-bottom: 5500%;}</style><div class="kill-ie"><h1><b>抱歉，您的浏览器无法访问本站</b></h1><h3>微软已经于2016年终止了对 Internet Explorer (IE) 10 及更早版本的支持，<br/>继续使用存在极大的安全隐患，请使用当代主流的浏览器进行访问。</h3><br/><a target="_blank" rel="noopener external nofollow noreferrer" href="https://www.microsoft.com/zh-cn/WindowsForBusiness/End-of-IE-support"><strong>了解详情 ></strong></a></div>')</script><noscript><style>html{overflow-x:hidden!important;overflow-y:hidden!important}.kill-noscript{text-align:center;height:100%;margin-top:15%;margin-bottom:5500%}</style><div class="kill-noscript"><h1><b>抱歉，您的浏览器无法访问本站</b></h1><h3>本页面需要浏览器支持（启用）JavaScript</h3><br> <a target="_blank" rel="noopener external nofollow noreferrer" href="https://www.baidu.com/s?wd=启用JavaScript"><strong>了解详情 ></strong></a></div></noscript></head><body><header id="l_header" class="l_header always shadow blur show"><div class="container"><div id="wrapper"><div class="nav-sub"><p class="title"></p><ul class="switcher nav-list-h m-phone" id="pjax-header-nav-list"><li><a id="s-comment" class="fas fa-comments fa-fw" target="_self" href="javascript:void(0)" rel="external nofollow noreferrer"></a></li><li><a id="s-toc" class="s-toc fas fa-list fa-fw" target="_self" href="javascript:void(0)" rel="external nofollow noreferrer"></a></li></ul></div><div class="nav-main"> <a class="title flat-box" target="_self" href="/"><img no-lazy class="logo" src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/img/cover/fav/cf_o1x64.jpg"></a><div class="menu navigation"><ul class="nav-list-h m-pc"><li><a class="menuitem flat-box faa-parent animated-hover" href="/" id="home"><i class="fas fa-home fa-fw"></i> Home</a></li><li><a class="menuitem flat-box faa-parent animated-hover"><i class="fas fa-th-list fa-fw"></i> Articles</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/categories/" id="categories"><i class="fas fa-folder-open fa-fw"></i> Categories</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/tags/" id="tags"><i class="fas fa-tags fa-fw"></i> Tags</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/archives/" id="archives"><i class="fas fa-archive fa-fw"></i> Archives</a></li></ul></li><li><a class="menuitem flat-box faa-parent animated-hover"><i class="fas fa-fan faa-spin animated fa-fw"></i> Play</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/catchTheCat/" id="catchTheCat"><i class="fas fa-cat faa-wrench animated-hover fa-fw"></i> Chat Noir</a></li></ul></li><li><a class="menuitem flat-box faa-parent animated-hover"><i class="fas fa-cog fa-spin fa-fw"></i> Tools</a><ul class="list-v"><li><a class="menuitem flat-box header toggle-mode-btn"><i class="fas fa-moon fa-fw"></i> 暗黑模式</a></li><li></li><li><a class="menuitem flat-box"><i class="fas fa-compact-disc fa-fw music"></i> Music</a><ul class="list-v"><li><div class="aplayer-container"><meting-js theme="#1BCDFC" autoplay="false" volume="0.7" loop="all" order="list" fixed="false" list-max-height="320px" server="netease" type="playlist" id="5472211102" list-folded="true"></meting-js></div></li></ul></li><li></li></ul></li><li><a class="menuitem flat-box faa-parent animated-hover"><i class="fas fa-info-circle fa-fw"></i> Me</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/about/" id="about"><i class="fas fa-ellipsis-v fa-fw"></i> About</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="https://aner1001.gitee.io/resume/" target="_blank" id="https:aner1001giteeioresume"><i class="fas fa-clock fa-fw"></i> Resume</a></li></ul></li></ul></div><div id="tp-weather-widget"></div><script>!function(e,t,n,a,i,o,c,r){r=function(){o=t.createElement(n),c=t.getElementsByTagName(n)[0],o.src=i,o.charset="utf-8",o.async=1,c.parentNode.insertBefore(o,c)},e.SeniverseWeatherWidgetObject=a,e[a]||(e[a]=function(){(e[a].q=e[a].q||[]).push(arguments)}),e[a].l=+new Date,e.attachEvent?e.attachEvent("onload",r):e.addEventListener("load",r,!1)}(window,document,"script","SeniverseWeatherWidget","//cdn.sencdn.com/widget2/static/js/bundle.js?t="+parseInt(((new Date).getTime()/1e8).toString(),10)),window.SeniverseWeatherWidget("show",{flavor:"slim",location:"WTW3SJ5ZBJUY",geolocation:!0,language:"zh-Hans",unit:"c",theme:"auto",token:"563a4097-8461-469b-ac30-123bac0010d1",hover:"enabled",container:"tp-weather-widget"})</script><div class="m_search"><form name="searchform" class="form u-search-form"><i class="icon fas fa-search fa-fw"></i> <input type="text" class="input u-search-input" placeholder="Search..."></form></div><ul class="switcher nav-list-h m-phone"><li><a class="s-search fas fa-search fa-fw" target="_self" href="javascript:void(0)" rel="external nofollow noreferrer"></a></li><li><a class="s-menu fas fa-bars fa-fw" target="_self" href="javascript:void(0)" rel="external nofollow noreferrer"></a><ul class="menu-phone list-v navigation white-box"><li><a class="menuitem flat-box faa-parent animated-hover" href="/" id="home"><i class="fas fa-home fa-fw"></i> Home</a></li><li><a class="menuitem flat-box faa-parent animated-hover"><i class="fas fa-th-list fa-fw"></i> Articles</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/categories/" id="categories"><i class="fas fa-folder-open fa-fw"></i> Categories</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/tags/" id="tags"><i class="fas fa-tags fa-fw"></i> Tags</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="/archives/" id="archives"><i class="fas fa-archive fa-fw"></i> Archives</a></li></ul></li><li><a class="menuitem flat-box faa-parent animated-hover"><i class="fas fa-fan faa-spin animated fa-fw"></i> Play</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/catchTheCat/" id="catchTheCat"><i class="fas fa-cat faa-wrench animated-hover fa-fw"></i> Chat Noir</a></li></ul></li><li><a class="menuitem flat-box faa-parent animated-hover"><i class="fas fa-cog fa-spin fa-fw"></i> Tools</a><ul class="list-v"><li><a class="menuitem flat-box header toggle-mode-btn"><i class="fas fa-moon fa-fw"></i> 暗黑模式</a></li><li></li></ul></li><li><a class="menuitem flat-box faa-parent animated-hover"><i class="fas fa-info-circle fa-fw"></i> Me</a><ul class="list-v"><li><a class="menuitem flat-box faa-parent animated-hover" href="/about/" id="about"><i class="fas fa-ellipsis-v fa-fw"></i> About</a></li><li><a class="menuitem flat-box faa-parent animated-hover" href="https://aner1001.gitee.io/resume/" target="_blank" id="https:aner1001giteeioresume"><i class="fas fa-clock fa-fw"></i> Resume</a></li></ul></li></ul></li></ul></div></div></div></header><div id="l_body"><div id="l_cover"><div id="full" class="cover-wrapper post blank" style="display:none"><div id="cover-backstretch"></div><div id="scroll-down" style="display:none"><i class="fa fa-chevron-down scroll-down-effects"></i></div></div></div><div id="safearea"><div class="body-wrapper" id="pjax-container"><div class="l_main"><article class="article post white-box reveal md shadow article-type-post" id="post" itemscope itemprop="blogPost"><div class="article-meta" id="top"><h1 class="title"> Git学习笔记</h1><div class="new-meta-box"><div class="new-meta-item author"> <a class="author" href="/" rel="nofollow"><img no-lazy src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/img/cover/fav/cf_1o_x16.jpg"><p>汤晔飞</p></a></div><div class="new-meta-item category"><a class="notlink"><i class="fas fa-folder-open fa-fw" aria-hidden="true"></i> <a class="category-link" href="/categories/%E6%8A%80%E6%9C%AF%E7%9F%A5%E8%AF%86/">技术知识</a><span class="sep"></span><a class="category-link" href="/categories/%E6%8A%80%E6%9C%AF%E7%9F%A5%E8%AF%86/%E5%B7%A5%E5%85%B7/">工具</a></a></div><div class="new-meta-item date"><a class="notlink"><i class="fas fa-calendar-alt fa-fw" aria-hidden="true"></i><p>发布于：2021年3月4日</p></a></div><div class="new-meta-item browse leancloud"><a class="notlink"><div id="lc-pv" data-title="Git学习笔记" data-path="/posts/2021/03/04/e55aa0d7a71b/"><i class="fas fa-eye fa-fw" aria-hidden="true"></i><span id="number"><i class="fas fa-circle-notch fa-spin fa-fw" aria-hidden="true"></i></span> 次浏览</div></a></div></div></div><p>Git工具学习笔记。主要参考了廖雪峰老师的学习网站。</p><span id="more"></span><blockquote><p>注：本文中如果使用了<file>,<branchname>，&lt;&gt;这些标签为了好的区分和显示效果才加上。实际写命令时不需要带上&lt;&gt;,直接写里面的名称内容就可以。</branchname></file></p></blockquote><h2 id="命令整理："><a class="header-anchor" href="#命令整理：">☀</a>命令整理：</h2><h3 id="创建版本库"><a class="header-anchor" href="#创建版本库">☀</a>创建版本库</h3><p><strong><code>init</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git init</span><br></pre></td></tr></table></figure><p>将当前所在目录变成Git可以管理的仓库。初始化本地版本库。</p><p><strong><code>clone</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> &lt;url&gt;   <span class="comment">#从远程仓库克隆,并关联远程仓库。</span></span><br></pre></td></tr></table></figure><h3 id="修改和提交"><a class="header-anchor" href="#修改和提交">☀</a>修改和提交</h3><p><strong><code>add</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">git add [文件名] 			<span class="comment">#添加单个文件</span></span><br><span class="line">git add [文件名] [文件名]    <span class="comment">#添加多个文件</span></span><br><span class="line">git add . 				  <span class="comment">#将所有修改的文件添加到暂存区。</span></span><br><span class="line">git add -f 				  <span class="comment">#强制添加。</span></span><br></pre></td></tr></table></figure><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td><code>-f</code></td><td>强制添加到git,使其修改被跟踪，跳过忽略文件验证。</td></tr></tbody></table><p><strong><code>commit</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git commit –m ”提交备注信息”   <span class="comment">#将文件提交到本地仓库。提交的是暂存区的版本。</span></span><br><span class="line">git commit --amend			<span class="comment">#覆盖上一次的提交内容和修改上一次提交描述。</span></span><br></pre></td></tr></table></figure><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td><code>--amend</code></td><td>覆盖上一次的提交内容和修改上一次提交描述。</td></tr></tbody></table><p><strong><code>status</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git status</span><br></pre></td></tr></table></figure><p>查看仓库的状态(文件的修改和提交状态)。<br> ⭐️当需要切换分支时，如果status命令查出当前分支有修改，先要stash，再切换，符合规范。否则会造成，切换后，被修改的文件，无法切换成目标分支所对应的实际状态。</p><p><strong><code>diff</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">git diff [文件名]     <span class="comment">#比较指定文件修改的地方。当前工作区中指定的文件进行比较。暂存区有add时，优先和暂存区比。未加到暂存区，和本地版本库最新的提交版本进行比较。</span></span><br><span class="line">git diff 			<span class="comment">#如果不写文件名，比较所有被修改的文件，功能相同，下方类似。</span></span><br><span class="line">git diff HEAD [文件名]   	<span class="comment">#比较的是工作区中指定的文件与版本库中文件的差异。HEAD指针指向当前，也可以写为HEAD^或者commit_id</span></span><br><span class="line">git diff HEAD    		   <span class="comment">#比较所有被修改的文件。</span></span><br><span class="line">git diff --cached 		   <span class="comment">#比较暂存区和版本库的所有文件差异。</span></span><br><span class="line">git diff --cached [文件名]  <span class="comment">#指定文件进行比较。</span></span><br></pre></td></tr></table></figure><table><thead><tr><th>参数</th><th>说明</th></tr></thead><tbody><tr><td><code>--cached</code><br><code>--staged</code></td><td>指定为暂存区文件。</td></tr></tbody></table><p><strong><code>rm</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">rm</span> &lt;file&gt;</span><br></pre></td></tr></table></figure><p>删除文件，文件区删除了文件，也需要将删除文件的修改操作记录到暂存区，才能commit。</p><p><strong><code>stash</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">git stash  			<span class="comment">#保存工作现场,工作区和暂存区。</span></span><br><span class="line">git stash apply		<span class="comment">#恢复工作现场。</span></span><br><span class="line">git stash drop		<span class="comment">#删除工作现场。</span></span><br><span class="line">git stash pop		<span class="comment">#恢复并删除工作现场。</span></span><br><span class="line">git stash list		<span class="comment">#查看保存的工作现场列表。</span></span><br><span class="line">git stash apply/drop/pop stash@&#123;0&#125;	<span class="comment">#操作指定工作现场。</span></span><br></pre></td></tr></table></figure><h3 id="查看提交日志"><a class="header-anchor" href="#查看提交日志">☀</a>查看提交日志</h3><p><strong><code>log</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">log</span>						<span class="comment">#查看版本库从开始直到当前的commit记录日志，最新的提交显示在第一行。</span></span><br><span class="line">git <span class="built_in">log</span> –-pretty=oneline	  <span class="comment">#美化成一行显示修改日志。</span></span><br><span class="line">git <span class="built_in">log</span> --graph				 <span class="comment">#可以看到分支合并图。</span></span><br><span class="line">git <span class="built_in">log</span> --graph --pretty=oneline --abbrev-commit	<span class="comment">#美化查看分支合并情况。</span></span><br><span class="line">git <span class="built_in">log</span> -p &lt;file&gt;		<span class="comment">#查看指定文件的提交历史。</span></span><br></pre></td></tr></table></figure><p>输入<code>wq</code>可以退出查看日志。</p><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td><code>--pretty=oneline</code></td><td>显示成一行。</td></tr><tr><td><code>--graph</code></td><td>将合并情况显示成图表形式。</td></tr><tr><td><code>--abbrev-commit</code></td><td>简化CommitId，取前几位显示。</td></tr></tbody></table><p><strong><code>reflog</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git reflog	<span class="comment"># 查看所有commit版本的提交和回退的记录。</span></span><br></pre></td></tr></table></figure><p>git reflog用来记录你的每一次命令。</p><p><strong><code>blame</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git blame &lt;file&gt;	<span class="comment">#以列表的方式查看指定文件的提交历史。</span></span><br></pre></td></tr></table></figure><h3 id="撤销"><a class="header-anchor" href="#撤销">☀</a>撤销</h3><p><strong><code>reset</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">git reset --hard HEAD</span><br><span class="line">git reset --hard HEAD</span><br><span class="line">git reset --hard commit_id		</span><br><span class="line"><span class="comment">#版本强制回退，HEAD^表示上一版本  HEAD^^表示上上版本，以此类推。这个版本回退是针对commit管理的所有版本库中的文件，包括了新增和删除的文件和单个文件本身内容的删除和修改。回退时，会将暂存区和文件区版本都被覆盖，和本地仓库指定回退到的版本一致。可以用cimmit_id来代替。</span></span><br><span class="line"></span><br><span class="line">git reset HEAD &lt;file&gt;</span><br><span class="line">git reset HEAD^ &lt;file&gt;</span><br><span class="line">git reset Commit_id &lt;file&gt;</span><br><span class="line"><span class="comment">#重置指定文件的暂存区内容,工作区内容不变。当HEAD为当前最新提交时，是丢弃暂存区。HEAD指向历史提交，则是将历史版本放入暂存区中。</span></span><br></pre></td></tr></table></figure><p><strong><code>checkout</code></strong>/<strong><code>restore</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git checkout &lt;file&gt;</span><br><span class="line">git restore &lt;file&gt;	<span class="comment">#(新版)</span></span><br></pre></td></tr></table></figure><p>两个语句功能一致，撤销工作区的修改，回到让这个文件回到最近一次git commit或git add时的状态。</p><p><strong><code>revert</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git revert &lt;commitId&gt;	<span class="comment">#撤销指定的提交。针对cherry-pick命令。单个的commitId回退操作。某个提交夹在了中间，就可以将该提交抽出来撤销掉。</span></span><br></pre></td></tr></table></figure><h3 id="分支与标签"><a class="header-anchor" href="#分支与标签">☀</a>分支与标签</h3><p><img src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205081459.png" class="lazyload" data-srcset="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205081459.png" srcset="" alt="Image"></p><p><strong><code>branch</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">git branch				<span class="comment">#查看本地的所有分支，已经当前指向的分支。</span></span><br><span class="line">git branch dev			<span class="comment">#基于当前分支的版本，创建一个平行的分支。</span></span><br><span class="line">git branch -d dev		<span class="comment">#删除本地某个分支。如果创建后进行提交过，则此命令会失效。</span></span><br><span class="line">git branch -D Feature	<span class="comment">#强制删除本地某个分支。</span></span><br><span class="line">git barnch -r			<span class="comment">#查看远程的分支。</span></span><br><span class="line">git branch -a 			<span class="comment">#查看本地和远程的所有分支。</span></span><br><span class="line">git branch -d -r &lt;branchname&gt; <span class="comment">#删除远程分支(只是在本地上删除，删除后还需推送到服务器).</span></span><br><span class="line">git branch -m &lt;oldbranch&gt; &lt;newbranch&gt; <span class="comment">#重命名本地分支</span></span><br></pre></td></tr></table></figure><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td><code>-d</code>,<code>--delete</code></td><td>删除分支。</td></tr><tr><td><code>-f</code>,<code>--force</code></td><td>强制。</td></tr><tr><td><code>-D</code>,<code>--delete --force</code></td><td>强制删除，即使分支上有过修改和提交。</td></tr><tr><td><code>-r</code>,<code>--remote</code></td><td>远程操作。</td></tr><tr><td><code>-a</code>,<code>--all</code></td><td>查看本地和远程的所有分支。</td></tr><tr><td><code>-m</code>,<code>--move</code></td><td>移动或重命名。</td></tr><tr><td><code>-M</code>,<code>-move --force</code></td><td>强制移动或重命名。</td></tr></tbody></table><p><strong><code>checkout</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git checkout dev		<span class="comment">#切换分支。</span></span><br><span class="line">git checkout -b dev		<span class="comment">#创建并切换分支</span></span><br></pre></td></tr></table></figure><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td><code>-b</code></td><td>创建分支。</td></tr></tbody></table><p><strong><code>switch</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git switch dev		<span class="comment">#切换分支(新)。</span></span><br><span class="line">git switch -c dev	<span class="comment">#创建并切换分支(新)。</span></span><br></pre></td></tr></table></figure><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td>-c</td><td>创建分支。</td></tr></tbody></table><p><strong>👿注意：</strong><br> 分支的切换，工作区会保留已修改的内容，暂存区会保存已添加到暂存区的内容。已提交但是还没被修改的内容会在工作区实时同步。<br> 所以切换分支使用前，尽量将所有分支内容都提交或者如果不能提交的<code>stash</code>起来，更加符合分支的时用思想。</p><p><strong><code>tag</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">git tag V1.0	<span class="comment">#为当前分支最新的commit创建标签。</span></span><br><span class="line">git tag			<span class="comment">#查看所有标签。</span></span><br><span class="line">git tag tagName commitId	<span class="comment">#为历史中指定的commit打上标签。</span></span><br><span class="line">git tag -a tagName -m <span class="string">&quot;message&quot;</span> commitId	<span class="comment">#创建带说明的标签</span></span><br><span class="line">git show tagName	<span class="comment">#查看标签信息所关联的提交信息(commitid，提交信息等)。</span></span><br><span class="line">git tag -d tagName	<span class="comment">#删除标签(删除的是本地的标签)。</span></span><br><span class="line">git push origin &lt;tagname&gt;	<span class="comment">#推送某个标签到远程。</span></span><br><span class="line">git push origin --tags		<span class="comment">#一次性推送尚未推送的所有标签到远程。</span></span><br></pre></td></tr></table></figure><p>标签和commitId都没有分支划分，是针对整个仓库的。</p><h3 id="合并"><a class="header-anchor" href="#合并">☀</a>合并</h3><p><strong><code>merge</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git merge dev	<span class="comment">#合并分支。</span></span><br><span class="line">git merge --no-ff -m <span class="string">&quot;merge with no-ff&quot;</span> dev   <span class="comment">#记录分支历史合并法。就是普通模式合并。</span></span><br><span class="line">git merge --abort <span class="comment">#回滚到合并之前</span></span><br></pre></td></tr></table></figure><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td><code>--no-ff</code></td><td>普通模式合并。不会覆盖当前提交，生成新的提交。</td></tr><tr><td><code>--abort</code></td><td>回滚到合并之前。</td></tr></tbody></table><p><code>merge</code>从合并的角度可理解为合并merge右侧指定的分支到当前分支。</p><p><strong><code>cherry-pick</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git cherry-pick commitId	<span class="comment">#针对某次修改的提交，合并到当前分支。</span></span><br></pre></td></tr></table></figure><p><strong><code>rebase</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git rebase		<span class="comment">#整理历史提交记录为一条直线。</span></span><br><span class="line">git rebase	&lt;branch&gt;	<span class="comment">#指定分支操作。</span></span><br></pre></td></tr></table></figure><p>如果是先提交，后拉取的操作，合并后，历史提交记录中会有合并产生。历史日志记录会显示合并的分叉线。该命令修改优化提交记录了抓变成先拉取后提交的操作，抹去合并的记录，使日志展现为一条直线。</p><h3 id="远程操作"><a class="header-anchor" href="#远程操作">☀</a>远程操作</h3><p><strong><code>remote</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">git remote 		<span class="comment">#查看远程库。</span></span><br><span class="line">git remote show origin	<span class="comment">#查看本地分支和追踪情况。</span></span><br><span class="line">git remote -v	<span class="comment">#查看远程库详细信息。</span></span><br><span class="line">git remote add origin git@server-name:path/repo-name.git 	<span class="comment">#添加远程库地址。</span></span><br><span class="line">git remote <span class="built_in">rm</span> origin	<span class="comment">#删除已有的远程仓库origin。</span></span><br><span class="line">git remote prune origin   <span class="comment">#同步删除远程已删除的远程分支。</span></span><br></pre></td></tr></table></figure><p><strong><code>push</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">git push -u origin master   <span class="comment">#远程库推送并绑定。</span></span><br><span class="line">git push origin master		<span class="comment">#指定远程库和分支进行推送。</span></span><br><span class="line">git push --force		    <span class="comment">#强制提交。</span></span><br><span class="line">git push origin:&lt;branchname&gt;	<span class="comment">#删除分支后推送至服务器。</span></span><br><span class="line">git push origin &lt;tagname&gt;	<span class="comment">#推送某个标签到远程。</span></span><br><span class="line">git push origin --tags		<span class="comment">#一次性推送尚未推送的所有标签到远程。</span></span><br></pre></td></tr></table></figure><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td>-u</td><td>将当前分支与远程库分支绑定。一般在第一次本地提交远程的时候使用。<br>因为已经绑定，以后直接使用简写<code>git push</code>命令即可。拉取的时候使用git pull。</td></tr><tr><td>–force</td><td>进行强制覆盖提交。</td></tr><tr><td>–tags</td><td>一次性推送尚未推送的所有标签到远程。</td></tr></tbody></table><p><strong><code>checkout</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git checkout -b dev origin/dev		<span class="comment">#创建本地库中拉取到的远程origin的dev分支，到本地并关联绑定.</span></span><br><span class="line">git branch --set-upstream-to=origin/dev dev		<span class="comment">#将本地分支与远程分支绑定，绑定后才能使用fetch和pull拉取。</span></span><br></pre></td></tr></table></figure><p>本地分支与远程分支绑定，如果未绑定是不能抓取分支的。(master分支再clone的时候默认绑定了。)(一般是本地push上去的分支，需要使用这个语句再绑定。名字尽量起得一样。)</p><p><strong><code>pull</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git pull 	<span class="comment">#抓取并合并已绑定的分支。</span></span><br><span class="line">git pull git@github.com:aner1001/gitlearn1.git master --allow-unrelated-histories  <span class="comment">#将本地仓库从一个commit不一致，无关的远程仓库中拉取，甚至名字都不一样。</span></span><br><span class="line">git pull &lt;远程主机名&gt; &lt;远程分支名&gt;:&lt;本地分支名&gt;	<span class="comment">#将远程主机的某个分支的更新取回，并与本地指定的分支合并，如果不指定，就是默认当前分支。</span></span><br></pre></td></tr></table></figure><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td><code>--allow-unrelated-histories</code></td><td>将本地仓库从一个commit不一致，无关的远程仓库中拉取。</td></tr><tr><td><code>-f</code>,<code>--force</code></td><td>强制覆盖本地版本。</td></tr></tbody></table><p><strong><code>fetch</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git fetch &lt;远程主机名&gt; <span class="comment">#这个命令将某个远程主机的更新全部取回本地.</span></span><br><span class="line">git fetch &lt;远程主机名&gt; &lt;分支名&gt; <span class="comment">#只想取回特定分支的更新,注意之间有空格. 本地会产生一个 FETCH_HEAD分支。</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="验证"><a class="header-anchor" href="#验证">☀</a>验证</h3><p><strong><code>check-ignore</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git check-ignore -v db.ini		<span class="comment">#验证查看文件匹配到的忽略ignore规则。</span></span><br></pre></td></tr></table></figure><h3 id="子模块"><a class="header-anchor" href="#子模块">☀</a>子模块</h3><p><strong><code>submodule</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">git submodule add  仓库地址   路径			  <span class="comment">#1.为当前工程添加submodule。</span></span><br><span class="line">git submoudle init 							 <span class="comment">#2.初始化子模块。</span></span><br><span class="line">git submoudle update						 <span class="comment">#3.更新子模块。</span></span><br><span class="line">git submodule update --init --recursive		   <span class="comment">#递归初始化并拉取更新所有子模块，效果=2和3.</span></span><br><span class="line">git submodule foreach  git checkout master      <span class="comment">#foreach对每个子模块进行操作。这里是切换到主分支。</span></span><br><span class="line">git submodule foreach git pull 				   <span class="comment">#拉取所有子模块，跳过父工程的版本号记录。</span></span><br><span class="line">git submodule deinit &lt;submodule-name&gt;			<span class="comment">#删除子模块。不是真正的删除，下方常用操作中详细说明。</span></span><br></pre></td></tr></table></figure><h3 id="配置"><a class="header-anchor" href="#配置">☀</a>配置</h3><p><strong><code>config</code></strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">git config --global user.name <span class="string">&quot;Your Name&quot;</span>    			<span class="comment">#设置终端管理git仓库的用户名。</span></span><br><span class="line">git config --global user.email <span class="string">&quot;email@example.com&quot;</span>	<span class="comment">#设置终端管理git仓库的邮件地址。</span></span><br><span class="line">git config --golbal color.ui.true					<span class="comment">#让Git显示颜色，会让命令输出看起来更醒目。</span></span><br><span class="line">git config --golbal alias.st status					<span class="comment">#为命令配置别名。</span></span><br></pre></td></tr></table></figure><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td><code>--global</code></td><td>global参数表示终端所有的仓库中都会使用这个配置，也可以对某个仓库指定不同的用户名和Email地址。<br>配置Git的时候，加上–global是针对当前用户起作用的，如果不加，那只针对当前的仓库起作用。</td></tr></tbody></table><h2 id="常用操作"><a class="header-anchor" href="#常用操作">☀</a>常用操作</h2><h3 id="生成SSH密钥，绑定Git服务器。"><a class="header-anchor" href="#生成SSH密钥，绑定Git服务器。">☀</a>生成SSH密钥，绑定Git服务器。</h3><ol><li><p>生成密钥:<br> 命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh-keygen -t rsa -C <span class="string">&quot;youremail@example.com&quot;</span></span><br></pre></td></tr></table></figure><p>你需要把邮件地址换成你自己的邮件地址，然后一路回车，使用默认值即可，由于这个Key也不是用于军事目的，所以也无需设置密码。</p></li><li><p>绑定git服务器<br> 登陆Git服务器，找到类似“Account settings”，“SSH Keys”页面：<br> 然后，点“Add SSH Key”，填上任意Title，在Key文本框里粘贴id_rsa.pub文件的内容</p></li><li><p>完成后在命令行链接测试，首次建立链接会要求信任主机。<br> 命令:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh -T git@具体git服务器域名</span><br></pre></td></tr></table></figure></li></ol><h3 id="本地库关联远程库，推送远程库"><a class="header-anchor" href="#本地库关联远程库，推送远程库">☀</a>本地库关联远程库，推送远程库</h3><p>这种情况针对于先有本地后有远程库。</p><ol><li>关联远程库。</li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git remote add origin git@server-name:path/repo-name.git</span><br></pre></td></tr></table></figure><p>参数注释：</p><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td>orgin</td><td>远程地址库标识变量名。</td></tr><tr><td>server-name</td><td>git网站地址。</td></tr><tr><td>path</td><td>账户名</td></tr><tr><td>repo-name</td><td>远程仓库名</td></tr></tbody></table><p>当本地项目没有生成秘钥，或者不方便生成秘钥，配置在服务器上。比如云端自动化部署场景。也可以使用https协议，在远程地址上添加用户名和密码或者使用生成的token，进行拉取和上传操作，密码和token类的一般存放在环境变量中比较安全。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git remote add origin https://用户名:密码@github.com/用户名/仓库名.git</span><br><span class="line">git remote add origin https://<span class="variable">$&#123;GITHUB_TOKEN&#125;</span>@github.com/用户名/仓库名.git</span><br></pre></td></tr></table></figure><p>在.git配置文件中可以进行修改。<br> <img src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205075832.png" class="lazyload" data-srcset="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205075832.png" srcset="" alt="Image"></p><ol start="2"><li><p>将本地库的内容推送到远程库上。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git push -u origin master</span><br></pre></td></tr></table></figure><p>参数注释：</p><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td>-u</td><td>Git不但会把本地的master分支内容推送的<br>远程新的master分支，还会把本地的master分支<br>和远程的master分支关联起来，在以后的推送<br>或者拉取时就可以简化命令。</td></tr><tr><td>origin</td><td>远程库标识名</td></tr><tr><td>master</td><td>分支名</td></tr></tbody></table></li></ol><h3 id="从远程仓库克隆"><a class="header-anchor" href="#从远程仓库克隆">☀</a>从远程仓库克隆</h3><p>命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> git@github.com:michaelliao/gitskills.git		<span class="comment">#SSH协议拉取。</span></span><br><span class="line">git <span class="built_in">clone</span> https://github.com/aner1001/gitskills.git		<span class="comment">#Https协议。</span></span><br><span class="line">git <span class="built_in">clone</span> -b dev  https://github.com/aner1001/gitskills.git	 <span class="comment">#指定分支拉取。</span></span><br></pre></td></tr></table></figure><table><thead><tr><th>参数</th><th>描述</th></tr></thead><tbody><tr><td><code>-b</code></td><td>指定分支进行拉取。</td></tr></tbody></table><p>当你从远程仓库克隆时，实际上Git自动把本地的master分支和远程的master分支对应起来了，并且，远程仓库的默认名称是origin。</p><h3 id="撤回修改"><a class="header-anchor" href="#撤回修改">☀</a>撤回修改</h3><p>1.需要丢弃工作期的修改，已提交到暂存区的，回退单最近的暂存区状态。未提交到暂存区，回退到最新的版本库状态。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git checkout file</span><br><span class="line">git restore file（高版本）</span><br></pre></td></tr></table></figure><p>2.丢弃已提交到暂存区的修改文件，丢弃后工作区内容不变。HEAD指向当前最新提交。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git reset HEAD file</span><br></pre></td></tr></table></figure><p>3.已经提交了一次到版本库，要撤回提交。使用版本撤回命令，回到上一版本，但是是针对所有文件的。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git reset --hard HEAD^</span><br></pre></td></tr></table></figure><p>4.针对单个文件恢复到版本库的状态，但是已提交了一版到暂存区。1和2配合使用。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git reset HEAD file 	<span class="comment">#1</span></span><br><span class="line">git checkout file		<span class="comment">#2</span></span><br></pre></td></tr></table></figure><p>​</p><p>5.针对单个文件恢复到历史版本库的某个状态。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git reset HEAD^/Commit_id file	 <span class="comment">#1.将文件的历史版本拉到暂存区。</span></span><br><span class="line">git checkout file				<span class="comment">#2.从暂存区中将历史版本同步到文件区。</span></span><br></pre></td></tr></table></figure><p><strong>❤️理解reset命令：</strong><br> 当HEAD为当前最新提交时，是丢弃暂存区。指向历史提交，则是将历史版本放入暂存区中。可以体会一下Git体会一下GIt丢弃暂存区和存入暂存区的想法。指向最新提交***<u>丢弃</u>*<strong>暂存区是因为版本库当前就是最新提交，checkout/restore直接就可以恢复到最新版，不需要再放到暂存区。指向历史版本</strong><u><em>存入</em></u>**暂存区是因为，checkout/restore命令，首先恢复的是暂存区中的内容，就会直接恢复到指定历史版本，而不会恢复最新版本库中的提交了。</p><h3 id="改写提交"><a class="header-anchor" href="#改写提交">☀</a>改写提交</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git commit --amend			<span class="comment">#覆盖上一次的提交内容和修改上一次提交描述。</span></span><br></pre></td></tr></table></figure><h3 id="删除分支同步远程"><a class="header-anchor" href="#删除分支同步远程">☀</a>删除分支同步远程</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git branch -d &lt;branchname&gt;		<span class="comment">#删除本地分支。</span></span><br><span class="line">git branch -d -r &lt;branchname&gt;	<span class="comment">#删除本地记录的远程分支。</span></span><br><span class="line">git push origin:&lt;branchname&gt;	<span class="comment">#将删除的分支同步到远程。</span></span><br></pre></td></tr></table></figure><h3 id="重命名分支"><a class="header-anchor" href="#重命名分支">☀</a>重命名分支</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">git branch -m &lt;oldbranch&gt; &lt;newbranch&gt;  <span class="comment">#重命名分支</span></span><br><span class="line">git branch -d -r &lt;oldbranch&gt;	<span class="comment">#删除旧远程分支。</span></span><br><span class="line">git push origin:&lt;branchname&gt;	<span class="comment">#将删除旧分支同步到远程。</span></span><br><span class="line">git push -u origin &lt;newbranch&gt;	<span class="comment">#push本地新分支到远程服务器。</span></span><br></pre></td></tr></table></figure><h3 id="同步已删除的远程分支"><a class="header-anchor" href="#同步已删除的远程分支">☀</a>同步已删除的远程分支</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git remote show origin		<span class="comment">#查看分支的追踪情况。</span></span><br><span class="line">git remote prune origin		 <span class="comment">#同步已删除的远程分支。</span></span><br><span class="line">git remote -D  &lt;branchname&gt;	 <span class="comment">#删除本地多余分支。</span></span><br></pre></td></tr></table></figure><h3 id="解决冲突"><a class="header-anchor" href="#解决冲突">☀</a>解决冲突</h3><p>当两个分支都在原修改基础上做过提交，合并时，对于修改同一个内容的地方会存在冲突。<img src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205101929.png" class="lazyload" data-srcset="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205101929.png" srcset="" alt="Image"></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git merge feature1</span><br></pre></td></tr></table></figure><p>这个时候使用合并分支语句，Git无法判断，只能试图把各自的修改合并起来。**这时候就必须首先解决冲突。解决冲突后，再提交，合并完成。**Git用<code>&lt;&lt;&lt;&lt;&lt;&lt;&lt;</code>，<code>=======</code>，<code>&gt;&gt;&gt;&gt;&gt;&gt;&gt;</code>标记出不同分支的内容，<code>&lt;&lt;&lt;&lt;&lt;&lt;&lt;</code>和<code>&gt;&gt;&gt;&gt;&gt;&gt;&gt;</code>对应不同分支中的内容，<code>=======</code>表示间隔。</p><p>注意：参与和合成的feature分支内容不会被改变。合成后，可以删除。如果feature分支要继续使用合并后的内容，直接和现有的master分支合并就可以，这时候就不会有冲突，应为已经合并过了，直接指向的是master分支。</p><p><strong>Fast Forward 和 no fast foward</strong></p><p>翻译为中文是：<br> 快速向前合并，和非快速向前合并。<br> 合并分支时，如果可能，在非指定的情况下git会使用Fast Forward模式，这时候会将当前的修改ID和被合并的修改内容直接对应覆盖原修改内容，放弃了原分支的修改内容，会丢掉此次的修改信息。<br> 如果使用no fast foward模式，Git就会在merge时生成一个新的commit，这样，从分支历史上就可以看出分支信息。<br> 命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git merge --no-ff -m <span class="string">&quot;merge with no-ff&quot;</span> dev</span><br></pre></td></tr></table></figure><p>图文理解：<br> no fast foward <code>--no-ff</code> 模式：<br> <img src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205102627.png" class="lazyload" data-srcset="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205102627.png" srcset="" alt="Image"></p><p>Fast Forward 模式(默认)<br> <img src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205103721.png" class="lazyload" data-srcset="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205103721.png" srcset="" alt="Image"></p><h3 id="分支策略"><a class="header-anchor" href="#分支策略">☀</a><strong>分支策略</strong></h3><blockquote><p>在实际开发中，我们应该按照几个基本原则进行分支管理：<br> 首先，master分支应该是非常稳定的，也就是仅用来发布新版本，平时不能在上面干活；<br> 那在哪干活呢？干活都在dev分支上，也就是说，dev分支是不稳定的，到某个时候，比如1.0版本发布时，再把dev分支合并到master上，在master分支发布1.0版本；<br> 你和你的小伙伴们每个人都在dev分支上干活，每个人都有自己的分支，时不时地往dev分支上合并就可以了。<br> 所以，团队合作的分支看起来就像这样：</p></blockquote><p><img src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205103800.png" class="lazyload" data-srcset="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205103800.png" srcset="" alt="Image"></p><p>Feature分支当开发一个新功能时，创建Feature分支。但是当该功能不需要，也不需要再合并到主分支的时候，需要将其销毁。</p><p>销毁命令：</p><p>Feature还未修改时，小D还可以验证，Feature是否已经被合并。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git branch -d Feature</span><br></pre></td></tr></table></figure><p>Feature已修改，但是还没有合并，使用大D，强制删除。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git branch -D Feature</span><br></pre></td></tr></table></figure><h3 id="处理紧急BUG，但是当前分支有修改还不能提交"><a class="header-anchor" href="#处理紧急BUG，但是当前分支有修改还不能提交">☀</a>处理紧急BUG，但是当前分支有修改还不能提交</h3><p>场景：当需要放下手头现在正在开发的工作，现在的工作还没开发完成，无法提交。而要立马去从事其他开发工作，例如短时间的修复BUG，或者紧急功能开发。</p><ol><li><p>保存工作现场</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git stash</span><br></pre></td></tr></table></figure><p>保存对象：——&gt;工作区的修改,和暂存区的修改与文件。 没有被Git管理的文件不会被保存。<br> 保存之后，当前工作区和暂存区所有的内容都被还原。</p></li><li><p>当修复BUG完后，回到刚才的工作分支，需要还原之前保存的工作现场。</p><p>查看保存的工作现场列表</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git stash list</span><br></pre></td></tr></table></figure></li><li><p>恢复工作现场</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git stash apply</span><br></pre></td></tr></table></figure></li><li><p>删除工作现场</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git stash drop</span><br></pre></td></tr></table></figure></li><li><p>恢复并删除工作现场</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git stash pop</span><br></pre></td></tr></table></figure></li><li><p>操作指定的工作现场</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git stash apply stash@&#123;0&#125;</span><br></pre></td></tr></table></figure><p>注意：当文件恢复时，如果修改的地方有冲突，那么会像合并分支一样，产生冲突文件。需要手工去解决冲突。</p></li></ol><p>当修改BUG后，BUG分支已经合并到主分支，并且BUG分支已经删除。这时候想在其他分支上也修复此BUG，但是其他分支不能和主分支完全合并，只需要修改BUG的那个提交。<br> 针对某次提交到当前分支。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git cherry-pick commitId</span><br></pre></td></tr></table></figure><p>❤️个人理解：针对某个单次提交进行的合并。merge实际上是针对所有的提交，多次的提交进行合并。合并的单操作和多操作的区别。</p><h3 id="拉取fetch-pull"><a class="header-anchor" href="#拉取fetch-pull">☀</a>拉取fetch&amp;pull</h3><p><img src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205204446.jpg" class="lazyload" data-srcset="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205204446.jpg" srcset="" alt="Image"></p><blockquote><p>可以简单的概括为：git fetch是将远程主机的最新内容拉到本地，用户在检查了以后决定是否合并到工作本机分支中。而git pull 则是将远程主机的最新内容拉下来后直接合并，即：git pull = git fetch + git merge，这样可能会产生冲突，需要手动解决。</p></blockquote><p>git fetch 命令：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git fetch &lt;远程主机名&gt; 			<span class="comment">#这个命令将某个远程主机的所有分支的更新全部取回本地。</span></span><br></pre></td></tr></table></figure><p>如果只想取回特定分支的更新，可以指定分支名：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git fetch &lt;远程主机名&gt; &lt;分支名&gt; 	<span class="comment">#注意之间有空格</span></span><br></pre></td></tr></table></figure><p>最常见的命令如取回origin 主机的master 分支：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git fetch origin master</span><br></pre></td></tr></table></figure><p>取回更新后，会返回一个FETCH_HEAD ，指的是某个branch在服务器上的最新状态，我们可以在本地通过它查看刚取回的更新信息：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">log</span> -p FETCH_HEAD</span><br></pre></td></tr></table></figure><p><img src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205205342.png" class="lazyload" data-srcset="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205205342.png" srcset="" alt="Image"></p><p>可以看到返回的信息包括更新的文件名，更新的作者和时间，以及更新的代码（19行红色[删除]和绿色[新增]部分）。我们可以通过这些信息来判断是否产生冲突，以确定是否将更新merge到当前分支。<br> 前面提到，git pull 的过程可以理解为：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git fetch origin master <span class="comment">#从远程主机的master分支拉取最新内容</span></span><br><span class="line">git merge FETCH_HEAD <span class="comment">#将拉取下来的最新内容合并到当前所在的分支中</span></span><br><span class="line">git merge origin/master		<span class="comment">#这样写应该也可以。拉个多个远程分支下来的时候。</span></span><br></pre></td></tr></table></figure><p>git pull命令：</p><p>即将远程主机的某个分支的更新取回，并与本地指定的分支合并，完整格式可表示为：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git pull &lt;远程主机名&gt; &lt;远程分支名&gt;:&lt;本地分支名&gt;</span><br></pre></td></tr></table></figure><p>如果远程分支是与当前分支合并，则冒号后面的部分可以省略：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git pull origin next</span><br></pre></td></tr></table></figure><p>-<code>f</code> 参数，远程库强制覆盖本地版本。push 指令后也可以加入，强制提交覆盖远程版本。</p><h3 id="Rebase"><a class="header-anchor" href="#Rebase">☀</a><strong>Rebase</strong></h3><p>整理历史提交记录为一条直线。<br> 针对多人合作的单条分支上，单人的分支合并仍然会显示三角。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git rebase</span><br></pre></td></tr></table></figure><p>会将GIt合并(远程与本地同分支)的三叉分支，整理为一条直线。但是这样也看不出来那几个分支做了合并。根据实际情况，需要再使用。<br> <img src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205112559.png" class="lazyload" data-srcset="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205112559.png" srcset="" alt="Image"></p><p>会将pull的版本提前，使其顺理成章的变成一条直线。<br> <img src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205112644.png" class="lazyload" data-srcset="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205112644.png" srcset="" alt="Image"></p><p>rebase操作可以把本地未push的分叉提交历史整理成直线；<br> rebase的目的是使得我们在查看历史提交的变化时更容易，因为分叉的提交需要三方对比。<br> 缺点是本地的分叉提交已经被修改过了。相当于将pull放在commit顺序后，重新进行了按次序多次修改，重新生成了commitID，变成了本地的最后一次commitID。需要再重新pull一次。<br> <img src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205155127.png" class="lazyload" data-srcset="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205155127.png" srcset="" alt="Image"><img src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205155136.png" class="lazyload" data-srcset="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205155136.png" srcset="" alt="Image"></p><h3 id="忽略特殊文件："><a class="header-anchor" href="#忽略特殊文件：">☀</a><strong>忽略特殊文件：</strong></h3><blockquote><p>忽略某些文件时，需要编写.gitignore</p></blockquote><blockquote><p>在Git工作区的根目录下创建一个特殊的.gitignore文件，然后把要忽略的文件名填进去，Git就会自动忽略这些文件。</p></blockquote><blockquote><p>.gitignore文件本身要放到版本库里，并且可以对.gitignore做版本管理！</p></blockquote><blockquote><p>在文本编辑器里“保存”或者“另存为”就可以把文件保存为.gitignore了。</p></blockquote><blockquote><p>GitHub上已经成型的准备好的配置文件库，可在线浏览， <a target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/github/gitignore">https://github.com/github/gitignore</a></p></blockquote><blockquote><p>忽略文件的原则是：</p><ol><li>忽略操作系统自动生成的文件，比如缩略图等；</li><li>忽略编译生成的中间文件、可执行文件等，也就是如果一个文件是通过另一个文件自动生成的，那自动生成的文件就没必要放进版本库，比如Java编译产生的.class文件；</li><li>忽略你自己的带有敏感信息的配置文件，比如存放口令的配置文件。</li></ol></blockquote><p>查看文件匹配到的忽略规则</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git check-ignore -v db.ini</span><br></pre></td></tr></table></figure><p>强制添加到Git,使其修改被跟踪，跳过忽略文件验证。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git add -f Desktop.ini</span><br></pre></td></tr></table></figure><p>如果强制添加到Git的文件，就匹配不到规则了。</p><h3 id="配置别名"><a class="header-anchor" href="#配置别名">☀</a><strong>配置别名</strong></h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">git config --global alias.st status</span><br><span class="line">git config --global alias.co checkout</span><br><span class="line">git config --global alias.ci commit</span><br><span class="line">git config --global alias.br branch</span><br></pre></td></tr></table></figure><p>撤销暂存区提交</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git config --global alias.unstage <span class="string">&#x27;reset HEAD&#x27;</span></span><br></pre></td></tr></table></figure><p>显示最后一次提交信息</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git config --global alias.last <span class="string">&#x27;log -1&#x27;</span></span><br></pre></td></tr></table></figure><p>配置漂亮的log</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git config --global alias.lg <span class="string">&quot;log --color --graph --pretty=format:&#x27;%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&lt;%an&gt;%Creset&#x27; --abbrev-commit&quot;</span></span><br></pre></td></tr></table></figure><p>🐤效果展示：<br> <img src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205161652.png" class="lazyload" data-srcset="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205161652.png" srcset="" alt="Image"></p><h3 id="配置文件"><a class="header-anchor" href="#配置文件">☀</a>配置文件</h3><p>1.每个仓库单独的Git配置文件都放在.git/config文件中</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cat</span> .git/config</span><br></pre></td></tr></table></figure><p>2.当前用户的Git配置文件放在用户主目录下的一个隐藏文件.gitconfig中。也就是—global 时配置的会保存在这里面。<br> <img src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205162913.png" class="lazyload" data-srcset="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205162913.png" srcset="" alt="Image"></p><p>删除别名时，修改这个配置文件，找到对应的行，删除即可。需要全部重新配置，删除配置文件，重新配置也可以。单独修改时，重新输入命令修改，覆盖原配置。</p><h3 id="子模块共代码库的版本管理"><a class="header-anchor" href="#子模块共代码库的版本管理">☀</a><strong>子模块共代码库的版本管理</strong></h3><p>开发过程中，经常会有一些通用的部分希望抽取出来做成一个公共库来提供给别的工程来使用，而公共代码库的版本管理是个麻烦的事情。使用git的git submodule命令，问题迎刃而解了。</p><h4 id="添加子模块"><a class="header-anchor" href="#添加子模块">☀</a><strong>添加</strong>子模块</h4><p>为当前工程添加submodule，命令如下：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git submodule add  仓库地址   路径</span><br></pre></td></tr></table></figure><p>仓库地址是指子模块仓库地址，路径指将子模块放置在当前工程下的路径 注意：路径不能以 / 结尾（会造成修改不生效）、不能是现有工程已有的目录（不能順利 Clone）<br> 命令执行完成，会在当前工程根路径下生成一个名为“.gitmodules”的文件，其中记录了子模块的信息。添加完成以后，再将子模块所在的文件夹添加到工程中即可，远程仓库中则会出现子模块@版本号的快捷方式。<br> <img src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205165548.png" class="lazyload" data-srcset="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210205165548.png" srcset="" alt="image-20210205165548895"></p><h4 id="查看子模块"><a class="header-anchor" href="#查看子模块">☀</a><strong>查看子模块</strong></h4><p>查看 <code>.gitmodules</code></p><h4 id="下载子模块"><a class="header-anchor" href="#下载子模块">☀</a><strong>下载子模块</strong></h4><p>当使用git clone下来的工程中带有submodule时，初始的时候，submodule的内容并不会自动下载下来的，此时，只需执行如下命令：<br> 方式1：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">git submoudle init         <span class="comment">#注：这个方法是根据.gitmodule的配置在.git的config配置中增加子模块配置。</span></span><br><span class="line">git submoudle update   <span class="comment">#注意：这个方法的意思是，更新到父工程中记录的子模块版本号，不会更新子模块版本库中最新的版本号。</span></span><br></pre></td></tr></table></figure><p>方式2：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git submodule update --init --recursive</span><br></pre></td></tr></table></figure><p>即可将子模块内容下载下来后工程才不会缺少相应的文件。</p><p>方式3：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#在克隆父工程时，直接使用递归命令</span></span><br><span class="line">git <span class="built_in">clone</span> 父工程地址 --recursive</span><br></pre></td></tr></table></figure><h4 id="❤子模块切换主线分支"><a class="header-anchor" href="#❤子模块切换主线分支">☀</a>❤子模块切换主线分支</h4><p>当子模块有多个分支时，根据实际的使用情况。cd到子模块目录中，切换主线分支。否则修改子模块会被记录到临时创建的分支上。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> <span class="string">&#x27;submodule&#x27;</span></span><br><span class="line">git checkout master</span><br></pre></td></tr></table></figure><p>全部统一切换：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git submodule foreach git checkout master</span><br></pre></td></tr></table></figure><h4 id="更新子模块"><a class="header-anchor" href="#更新子模块">☀</a>更新子模块</h4><p><strong>场景1：当父工程记录的子模块版本更新后，更新父工程中的子模块。</strong></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git submodule update</span><br></pre></td></tr></table></figure><p><strong>场景2：子模块更新，但是父工程记录的子模块未更新时，更新子模块操作。</strong></p><p>单个子模块更新：<br> 进入子模块中，调整主线分支，使用git操作pull。最终父工程再提交一次，记录子模块更新后的版本。</p><p>多个子模块跟新：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git submodule foreach git pull <span class="comment">#拉取所有子模块，跳过父工程的版本号记录。</span></span><br></pre></td></tr></table></figure><p>更新完成后，需要将父工程中新的子模块版本号，<code>commit +push</code>。</p><h4 id="删除"><a class="header-anchor" href="#删除">☀</a><strong>删除</strong></h4><p>经过网上的各个版本总结的一个有效方案：</p><ol><li><p>删除子模块文件和.git config的配置信息。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git submodule deinit &lt;submodule-name&gt;</span><br></pre></td></tr></table></figure></li><li><p>删除子模块缓存：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">rm</span> --cached path_to_submodule</span><br><span class="line"><span class="comment">#补充：参数-r  =递归</span></span><br><span class="line">git <span class="built_in">rm</span> -r --cached .  <span class="comment">#文件夹下的所有文件缓存删除。如果缓存删不干净用这个。</span></span><br></pre></td></tr></table></figure></li><li><p>删除子模块空文件夹</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">rm</span> -rf 子模块文件夹</span><br></pre></td></tr></table></figure></li><li><p>删除.git下的缓存模块。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">rm</span> -rf .git/module/path_to_submodule</span><br></pre></td></tr></table></figure></li><li><p>删除.gitmodules中的配置信息，在全部清除的情况下或者整个文件都可以删除。</p></li><li><p>前五部就将子模块删除干净了。如果需要重新添加子模块。<code>git submodule add</code>新子模块即可。</p></li></ol><h3 id="自定义第三方库，同时保持第三方库的官方更新。"><a class="header-anchor" href="#自定义第三方库，同时保持第三方库的官方更新。">☀</a>自定义第三方库，同时保持第三方库的官方更新。</h3><ol><li><p>自己有一个 fork 的三方项目。没有的话直接去第三方项目fork。</p></li><li><p>克隆自己fork的第三方项目,或者添加到子模块的方式，将fork库添加到本地。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git <span class="built_in">clone</span> /   git submodule add  [address]  [path]</span><br></pre></td></tr></table></figure></li><li><p>cd进入仓库，查看远程库信息。</p></li></ol><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git remote -v</span><br></pre></td></tr></table></figure><ol start="5"><li><p>自己fork的项目中，本地添加一个三方的源。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git remote add dist_upstream  [第三方源地址]</span><br></pre></td></tr></table></figure></li><li><p>在自己fork的项目进行自定义改造并提交。如果是子模块则按照子模块的方式提交。</p></li><li><p>当原第三方库有了更新后。需要将更新纳入自己的fork中时。<br> 方法1：<br> pull拉取合并一个分支的方式.</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git pull dist_upstream master</span><br></pre></td></tr></table></figure><p>如果有冲突，解决冲突合并后,进行提交。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git push origin master</span><br></pre></td></tr></table></figure><p>方法2：<br> fetch拉取全部的分支，选择一个合并的分支,如果有冲突，解决冲突后，进行提交。</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">git fetch dist_upstream</span><br><span class="line">git merge dist_upstream/master</span><br><span class="line">git push origin master</span><br></pre></td></tr></table></figure></li></ol><p>+++</p><h2 id="知识整理"><a class="header-anchor" href="#知识整理">☀</a>知识整理</h2><ul><li><p>图片、视频、Word文件这些二进制文件，git无法跟踪变化，只能知道改动大小。</p></li><li><p>千万不要使用Windows自带的记事本编辑任何文本文件。<br> 原因是Microsoft开发记事本的团队使用了一个非常弱智的行为来保存UTF-8编码的文件，他们自作聪明地在每个文件开头添加了0xefbbbf（十六进制）的字符，你会遇到很多不可思议的问题，比如，网页第一行可能会显示一个“?”，明明正确的程序一编译就报语法错误，等等，都是由记事本的弱智行为带来的。使用EditPlus或者比较主流的编辑器。</p></li><li><p>Git中存在指向本地支线的一个指针叫HEAD。</p></li><li><p>HEAD与master<br> 一开始的时候，master分支是一条线，Git用master指向最新的提交，再用HEAD指向master，就能确定当前分支，以及当前分支的提交点。<br> <img src="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210204110129.png" class="lazyload" data-srcset="https://yefeit-note-picbed.oss-cn-shanghai.aliyuncs.com/blog/2021/02/04/20210204110129.png" srcset="" alt="Image"></p></li><li><p>id_rsa是私钥，不能泄露出去，id_rsa.pub是公钥，可以放心地告诉任何人。</p></li><li><p>Git支持多种传输协议<br> ssh协议: <a href="mailto:git@github.com" rel="external nofollow noreferrer">git@github.com</a>:michaelliao/gitskills.git -本地Git仓库和远程仓库之间的传输是通过SSH加密的。</p><p>​ https协议: <a target="_blank" rel="noopener external nofollow noreferrer" href="https://github.com/michaelliao/gitskills.git">https://github.com/michaelliao/gitskills.git</a></p><p>​ 区别：使用https除了速度慢以外，还有个最大的麻烦是每次推送都必须输入口令，但是在某些只开放http端口的公司内部就无法使用ssh协议而只能用https。SSH协议只认机器，HTTPS协议只认账号；也即为： 如果使用SSH操作远程仓库的话，我们需要使用公钥和私钥对来做权限的认证，如果使用HTTPS操作远程 仓库，则需要使用账号密码来做权限的认证。无论是公钥私钥对，还是账号密码，都只做权限的认证；</p></li><li><p>邮箱：<br> 1.关于git邮箱涉及到三处：<br> 1）git config 时为仓库配置的提交者邮箱。$ git config --global user.email “<a href="mailto:email@example.com" rel="external nofollow noreferrer">email@example.com</a>”<br> 2）git 生成秘钥时，所使用的的邮箱。 $ ssh-keygen -t rsa -C <a href="mailto:youremail@example.com" rel="external nofollow noreferrer">youremail@example.com</a><br> 3）git网站，账号所注册的邮箱。</p><p>2.三个邮箱有没有直接关联和验证同步。<br> 测试结果：当git生成秘钥时所使用的邮箱和git网站所注册的邮箱不一致时，仍然可以进行操作网站中的git仓库。</p><p>3.理解：<br> 1 )git config 时为仓库配置的提交者邮箱，只为了远程仓库记录下这些操作是由谁来完成的。远程仓库里需要记录这些提交记录是由谁来完成的；所以我们需要给本地的git设置用户名和邮箱，用于从本地仓库向远程仓库提交记录时，在远程仓库记录下这些操作是由谁来完成的。</p><p>​ 2 )生成秘钥的邮箱只为了，验证机器而存在。</p><p>​ 3 ) git网站所注册的邮箱，就是注册时绑定的，可能用来找回密码，或者GIt上做了一些操作进行实时通知。</p><p>4、官方解释：<br> 1）为什么要配置用户名和邮箱？<br> 因为Git是分布式版本控制系统，所以，每个机器都必须自报家门：你的名字和Email地址（名字和邮箱都不会进行验证），这样远程仓库才知道哪次提交是由谁完成的。你也许会担心，如果有人故意冒充别人怎么办？这个不必担心，首先我们相信大家都是善良无知的群众，其次，真的有冒充的也是有办法可查的。</p><pre><code>  2）配置的用户名和邮箱对push代码到远程仓库有什么影响？
   首先，配置的用户名和邮箱对push代码到远程仓库时的身份验证没有作用，即不用他们进行身份验证；他们仅仅会出现在远程仓库的commits里。
其次，按正常操作来说，你应该配置你的真实用户名和邮箱，这样一来在远程仓库的commits里可以看到哪个操作是你所为。
最后，这个用户名和邮箱是可以随便配置的（不提倡），如果你配置的邮箱是github里真实存在的邮箱，则commits里显示的是这个邮箱对应的账号；如果配置的邮箱是一个在github里不存在的邮箱，则commits里显示的是你配置的用户名。
</code></pre></li><li><p>Git的优秀之处：</p><ol><li>因为Git跟踪并管理的是修改，而非文件。</li><li>分布式版本系统的最大好处之一是在本地工作完全不需要考虑远程库的存在，也就是有没有联网都可以正常工作，而SVN在没有联网的时候是拒绝干活的！当有网络的时候，再把本地提交推送一下就完成了同步，真是太方便了！</li></ol></li><li><p>**下载：**如果下载太慢可以用镜像网站：<a target="_blank" rel="noopener external nofollow noreferrer" href="https://npm.taobao.org/mirrors/git-for-windows/">https://npm.taobao.org/mirrors/git-for-windows/</a></p></li></ul><div class="footer"><div class="copyright"><blockquote><p>博客内容遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议</p><p>本文永久链接是：<a href="http://aner1001.gitee.io/posts/2021/03/04/e55aa0d7a71b/">http://aner1001.gitee.io/posts/2021/03/04/e55aa0d7a71b/</a></p></blockquote></div></div><div class="article-meta" id="bottom"><div class="new-meta-box"><div class="new-meta-item date" itemprop="dateUpdated" datetime="2021-03-04T10:10:11+08:00"><a class="notlink"><i class="fas fa-edit fa-fw" aria-hidden="true"></i><p>更新于：2021年3月4日</p></a></div><div class="new-meta-item meta-tags"><a class="tag" href="/tags/Git/" rel="nofollow"><i class="fas fa-hashtag fa-fw" aria-hidden="true"></i><p>Git</p></a></div><div class="new-meta-item share -mob-share-list"><div class="-mob-share-list share-body"> <a class="-mob-share-qq" title="" rel="external nofollow noopener noreferrer noopener" target="_blank" href="http://connect.qq.com/widget/shareqq/index.html?url=http://aner1001.gitee.io/posts/2021/03/04/e55aa0d7a71b/&title=Git学习笔记 - Tang's blog.&summary=Git工具学习笔记。主要参考了廖雪峰老师的学习网站。"><img src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/qq.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/qq.png" srcset=""></a> <a class="-mob-share-qzone" title="" rel="external nofollow noopener noreferrer noopener" target="_blank" href="https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url=http://aner1001.gitee.io/posts/2021/03/04/e55aa0d7a71b/&title=Git学习笔记 - Tang's blog.&summary=Git工具学习笔记。主要参考了廖雪峰老师的学习网站。"><img src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/qzone.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/qzone.png" srcset=""></a> <a class="-mob-share-weibo" title="" rel="external nofollow noopener noreferrer noopener" target="_blank" href="http://service.weibo.com/share/share.php?url=http://aner1001.gitee.io/posts/2021/03/04/e55aa0d7a71b/&title=Git学习笔记 - Tang's blog.&summary=Git工具学习笔记。主要参考了廖雪峰老师的学习网站。"><img src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/weibo.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/weibo.png" srcset=""></a><div class="hoverbox"> <a class="share"><img src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/wechat.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/wechat.png" srcset=""></a><div class="target"> <img src=""></div></div> <a class="-mob-share-telegram" title="" rel="external nofollow noopener noreferrer noopener" target="_blank" href="https://t.me/share/url?url=http://aner1001.gitee.io/posts/2021/03/04/e55aa0d7a71b/&text=Git学习笔记 - Tang's blog."><img src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/telegram.png" class="lazyload" data-srcset="https://cdn.jsdelivr.net/gh/volantis-x/cdn-org/logo/128/telegram.png" srcset=""></a></div></div></div></div><div class="prev-next"><a class="prev" href="/posts/2021/03/04/3d827be8af75/"><p class="title"><i class="fas fa-chevron-left" aria-hidden="true"></i>Linux学习笔记</p><p class="content"> ☀Linux的概述： ☀学习Linux之前先了解Unix Unix是一个强大的多用户、多任务操作系统。于1969年在AT&amp;T的贝尔实验室开发。UNIX的商标权由国际开放标准组织（The...</p></a><a class="next" href="/posts/2021/03/03/477e70e48710/"><p class="title">Springboot学习笔记5-数据源配置<i class="fas fa-chevron-right" aria-hidden="true"></i></p><p class="content"> springboot配置数据源 ​ Spring Framework 为 SQL 数据库提供了广泛的支持。从直接使用 JdbcTemplate 进行 JDBC 访问到完全的对象关系映射（ob...</p></a></div></article><article class="post white-box reveal shadow" id="comments"><p ct><i class="fas fa-comments"></i> 评论</p><div id="valine_container" class="valine_thread"><i class="fas fa-cog fa-spin fa-fw fa-2x"></i></div></article></div><aside class="l_side"><section class="widget toc-wrapper shadow desktop mobile" id="toc-div"><header><i class="fas fa-list fa-fw" aria-hidden="true"></i> <span class="name">本文目录</span></header><div class="content"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%91%BD%E4%BB%A4%E6%95%B4%E7%90%86%EF%BC%9A"><span class="toc-text">命令整理：</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%88%9B%E5%BB%BA%E7%89%88%E6%9C%AC%E5%BA%93"><span class="toc-text">创建版本库</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BF%AE%E6%94%B9%E5%92%8C%E6%8F%90%E4%BA%A4"><span class="toc-text">修改和提交</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%9F%A5%E7%9C%8B%E6%8F%90%E4%BA%A4%E6%97%A5%E5%BF%97"><span class="toc-text">查看提交日志</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%92%A4%E9%94%80"><span class="toc-text">撤销</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%88%86%E6%94%AF%E4%B8%8E%E6%A0%87%E7%AD%BE"><span class="toc-text">分支与标签</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%90%88%E5%B9%B6"><span class="toc-text">合并</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%BF%9C%E7%A8%8B%E6%93%8D%E4%BD%9C"><span class="toc-text">远程操作</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%AA%8C%E8%AF%81"><span class="toc-text">验证</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AD%90%E6%A8%A1%E5%9D%97"><span class="toc-text">子模块</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%85%8D%E7%BD%AE"><span class="toc-text">配置</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%B8%B8%E7%94%A8%E6%93%8D%E4%BD%9C"><span class="toc-text">常用操作</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%94%9F%E6%88%90SSH%E5%AF%86%E9%92%A5%EF%BC%8C%E7%BB%91%E5%AE%9AGit%E6%9C%8D%E5%8A%A1%E5%99%A8%E3%80%82"><span class="toc-text">生成SSH密钥，绑定Git服务器。</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%9C%AC%E5%9C%B0%E5%BA%93%E5%85%B3%E8%81%94%E8%BF%9C%E7%A8%8B%E5%BA%93%EF%BC%8C%E6%8E%A8%E9%80%81%E8%BF%9C%E7%A8%8B%E5%BA%93"><span class="toc-text">本地库关联远程库，推送远程库</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BB%8E%E8%BF%9C%E7%A8%8B%E4%BB%93%E5%BA%93%E5%85%8B%E9%9A%86"><span class="toc-text">从远程仓库克隆</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%92%A4%E5%9B%9E%E4%BF%AE%E6%94%B9"><span class="toc-text">撤回修改</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%94%B9%E5%86%99%E6%8F%90%E4%BA%A4"><span class="toc-text">改写提交</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%88%A0%E9%99%A4%E5%88%86%E6%94%AF%E5%90%8C%E6%AD%A5%E8%BF%9C%E7%A8%8B"><span class="toc-text">删除分支同步远程</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%87%8D%E5%91%BD%E5%90%8D%E5%88%86%E6%94%AF"><span class="toc-text">重命名分支</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%90%8C%E6%AD%A5%E5%B7%B2%E5%88%A0%E9%99%A4%E7%9A%84%E8%BF%9C%E7%A8%8B%E5%88%86%E6%94%AF"><span class="toc-text">同步已删除的远程分支</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%A7%A3%E5%86%B3%E5%86%B2%E7%AA%81"><span class="toc-text">解决冲突</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%88%86%E6%94%AF%E7%AD%96%E7%95%A5"><span class="toc-text">分支策略</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%A4%84%E7%90%86%E7%B4%A7%E6%80%A5BUG%EF%BC%8C%E4%BD%86%E6%98%AF%E5%BD%93%E5%89%8D%E5%88%86%E6%94%AF%E6%9C%89%E4%BF%AE%E6%94%B9%E8%BF%98%E4%B8%8D%E8%83%BD%E6%8F%90%E4%BA%A4"><span class="toc-text">处理紧急BUG，但是当前分支有修改还不能提交</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%8B%89%E5%8F%96fetch-pull"><span class="toc-text">拉取fetch&amp;pull</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Rebase"><span class="toc-text">Rebase</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%BF%BD%E7%95%A5%E7%89%B9%E6%AE%8A%E6%96%87%E4%BB%B6%EF%BC%9A"><span class="toc-text">忽略特殊文件：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%85%8D%E7%BD%AE%E5%88%AB%E5%90%8D"><span class="toc-text">配置别名</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6"><span class="toc-text">配置文件</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%AD%90%E6%A8%A1%E5%9D%97%E5%85%B1%E4%BB%A3%E7%A0%81%E5%BA%93%E7%9A%84%E7%89%88%E6%9C%AC%E7%AE%A1%E7%90%86"><span class="toc-text">子模块共代码库的版本管理</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%B7%BB%E5%8A%A0%E5%AD%90%E6%A8%A1%E5%9D%97"><span class="toc-text">添加子模块</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%9F%A5%E7%9C%8B%E5%AD%90%E6%A8%A1%E5%9D%97"><span class="toc-text">查看子模块</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%B8%8B%E8%BD%BD%E5%AD%90%E6%A8%A1%E5%9D%97"><span class="toc-text">下载子模块</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E2%9D%A4%E5%AD%90%E6%A8%A1%E5%9D%97%E5%88%87%E6%8D%A2%E4%B8%BB%E7%BA%BF%E5%88%86%E6%94%AF"><span class="toc-text">❤子模块切换主线分支</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%9B%B4%E6%96%B0%E5%AD%90%E6%A8%A1%E5%9D%97"><span class="toc-text">更新子模块</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%88%A0%E9%99%A4"><span class="toc-text">删除</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%AC%AC%E4%B8%89%E6%96%B9%E5%BA%93%EF%BC%8C%E5%90%8C%E6%97%B6%E4%BF%9D%E6%8C%81%E7%AC%AC%E4%B8%89%E6%96%B9%E5%BA%93%E7%9A%84%E5%AE%98%E6%96%B9%E6%9B%B4%E6%96%B0%E3%80%82"><span class="toc-text">自定义第三方库，同时保持第三方库的官方更新。</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%9F%A5%E8%AF%86%E6%95%B4%E7%90%86"><span class="toc-text">知识整理</span></a></li></ol></div></section></aside><script>window.pdata={},pdata.ispage=!0,pdata.postTitle="Git学习笔记",pdata.commentPath="",pdata.commentPlaceholder="";var l_header=document.getElementById("l_header");l_header.classList.add("show");var cover_wrapper=document.querySelector(".cover-wrapper");cover_wrapper.id="none",cover_wrapper.style.display="none"</script></div><footer class="footer clearfix"><br><br><div class="aplayer-container"><meting-js theme="#1BCDFC" autoplay="false" volume="0.7" loop="all" order="list" fixed="false" list-max-height="320px" server="netease" type="playlist" id="5472211102" list-folded="true"></meting-js></div><br><div class="social-wrapper"><a href="/atom.xml" class="social fas fa-rss flat-btn" target="_blank" rel="external nofollow noopener noreferrer"></a><a href="mailto:584856024@qq.com" class="social fas fa-envelope flat-btn" target="_blank" rel="external nofollow noopener noreferrer"></a><a href="https://github.com/aner1001" class="social fab fa-github flat-btn" target="_blank" rel="external nofollow noopener noreferrer"></a><a href="https://music.163.com/#/user/home?id=1402271985" class="social fas fa-headphones-alt flat-btn" target="_blank" rel="external nofollow noopener noreferrer"></a></div><div><p>博客内容遵循 <a target="_blank" rel="noopener external nofollow noreferrer" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh">署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议</a></p></div><div><p><span id="lc-sv">本站总访问量为<span id="number"><i class="fas fa-circle-notch fa-spin fa-fw" aria-hidden="true"></i></span> 次</span> <span id="lc-uv">访客数为<span id="number"><i class="fas fa-circle-notch fa-spin fa-fw" aria-hidden="true"></i></span> 人</span></p></div> 本站使用 <a href="https://github.com/volantis-x/hexo-theme-volantis/tree/4.3.1" rel="external nofollow noreferrer" target="_blank" class="codename">Volantis</a> 作为主题，总访问量为<span id="busuanzi_value_site_pv"><i class="fas fa-circle-notch fa-spin fa-fw" aria-hidden="true"></i></span> 次<div class="copyright"><p><a href="/">Copyright © 2021-2021 XXX</a></p></div></footer><a id="s-top" class="fas fa-arrow-up fa-fw" href="javascript:void(0)" rel="external nofollow noreferrer"></a></div></div><div><script>function VPjax(){function e(e,t){this.name=t||e.name,this.run=()=>{e()}}this.list=[],this.start=()=>{for(var e=0;e<this.list.length;e++)this.list[e].run()},this.push=(t,n)=>{var i=new e(t,n);this.list.push(i)}}function loadScript(e,t){setTimeout((function(){var n=document.getElementsByTagName("head")[0]||document.documentElement,i=document.createElement("script");i.setAttribute("type","text/javascript"),t&&(i.onload=t),i.setAttribute("src",e),n.appendChild(i)}))}window.volantis={},window.volantis.loadcss=document.getElementById("loadcss"),volantis.pjax={},volantis.pjax.method={complete:new VPjax,error:new VPjax,send:new VPjax},volantis.pjax={...volantis.pjax,push:volantis.pjax.method.complete.push,error:volantis.pjax.method.error.push,send:volantis.pjax.method.send.push};var loadCSS=function(e,t,n,i){var o,a=window.document,s=a.createElement("link");if(t)o=t;else{var r=(a.body||a.getElementsByTagName("head")[0]).childNodes;o=r[r.length-1]}var d=a.styleSheets;if(i)for(var l in i)i.hasOwnProperty(l)&&s.setAttribute(l,i[l]);s.rel="stylesheet",s.href=e,s.media="only x",function e(t){if(a.body)return t();setTimeout((function(){e(t)}))}((function(){o.parentNode.insertBefore(s,t?o:o.nextSibling)}));var u=function(e){for(var t=s.href,n=d.length;n--;)if(d[n].href===t)return e();setTimeout((function(){u(e)}))};function h(){s.addEventListener&&s.removeEventListener("load",h),s.media=n||"all"}return s.addEventListener&&s.addEventListener("load",h),s.onloadcssdefined=u,u(h),s}</script><script>loadCSS("https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.14/css/all.min.css",window.volantis.loadcss),loadCSS("https://cdn.jsdelivr.net/gh/l-lin/font-awesome-animation/dist/font-awesome-animation.min.css",window.volantis.loadcss),loadCSS("https://cdn.jsdelivr.net/npm/node-waves@0.7.6/dist/waves.min.css",window.volantis.loadcss)</script><script src="https://cdn.jsdelivr.net/npm/jquery@3.5/dist/jquery.min.js"></script><script>function pjax_fancybox(){$(".md .gallery").find("img").each((function(){var a=document.createElement("a");$(a).attr("class","fancybox"),$(a).attr("pjax-fancybox",""),$(a).attr("href",$(this).attr("src")),$(this).attr("data-original")&&$(a).attr("href",$(this).attr("data-original")),$(a).attr("data-fancybox","images");var t="";$(this).attr("alt")&&($(a).attr("data-caption",$(this).attr("alt")),t=$(this).attr("alt"));var n=document.createElement("div");$(n).addClass("fancybox"),$(this).wrap(n);var o=document.createElement("span");$(o).addClass("image-caption"),$(o).text(t),$(this).after(o),$(this).wrap(a)})),$(".md .gallery").find("img").fancybox({selector:'[data-fancybox="images"]',hash:!1,loop:!1,closeClick:!0,helpers:{overlay:{closeClick:!0}},buttons:["zoom","close"]})}function SCload_fancybox(){0!=$(".md .gallery").find("img").length&&(loadCSS("https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css",document.getElementById("loadcss")),loadScript("https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js",pjax_fancybox))}function Pjax_SCload_fancybox(){void 0===$.fancybox?SCload_fancybox():pjax_fancybox()}$((function(){SCload_fancybox()})),volantis.pjax.push(Pjax_SCload_fancybox),volantis.pjax.send(()=>{void 0!==$.fancybox&&$.fancybox.close()},"fancybox")</script><script src="https://cdn.jsdelivr.net/npm/jquery-backstretch@2.1.18/jquery.backstretch.min.js"></script><script type="text/javascript">var imgs=["https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/001.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/002.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/003.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/004.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/005.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/006.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/012.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/016.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/019.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/025.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/033.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/034.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/035.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/038.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/039.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/042.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/046.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/051.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/052.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/054.jpg","https://cdn.jsdelivr.net/gh/volantis-x/cdn-wallpaper-minimalist/2020/056.jpg"];{function shuffle(t){for(var n=t.length;n--;){var i=Math.floor(Math.random()*n),l=t[i];t[i]=t[n],t[n]=l}}shuffle(imgs)}function Pjax_backstretch(){$("#cover-backstretch").backstretch(imgs,{duration:"10000",fade:"1500"})}loadScript("https://cdn.jsdelivr.net/npm/jquery-backstretch@2.1.18/jquery.backstretch.min.js",Pjax_backstretch)</script><div id="rightmenu-wrapper"><ul class="list-v rightmenu" id="rightmenu-content"><li class="option"><a class="vlts-menu opt fix-cursor-default" id="menu-copy-text" onclick='document.execCommand("copy")'><i class="fa fa-copy fa-fw"></i> 复制文本</a><hr id="hr-text"><a class="vlts-menu opt fix-cursor-default" id="menu-copy-href"><i class="fa fa-link fa-fw"></i> 复制链接</a><a class="vlts-menu opt fix-cursor-default" id="menu-open-href"><i class="fa fa-external-link-square-alt fa-fw"></i> 在新标签页打开</a><hr id="hr-href"><a class="vlts-menu opt fix-cursor-default" id="menu-copy-src"><i class="fa fa-image fa-fw"></i> 复制图片地址</a><hr id="hr-src"></li><li class="navigation"><a class="nav icon-only fix-cursor-default" onclick="history.back()"><i class="fa fa-arrow-left fa-fw"></i></a><a class="nav icon-only fix-cursor-default" onclick="history.forward()"><i class="fa fa-arrow-right fa-fw"></i></a><a class="nav icon-only fix-cursor-default" onclick="window.location.reload()"><i class="fa fa-redo fa-fw"></i></a><a class="nav icon-only fix-cursor-default" href="/"><i class="fa fa-home fa-fw"></i></a></li><hr><li><a class="vlts-menu fix-cursor-default" href="https://volantis.js.org/faqs/" id="https:volantisjsorgfaqs"><i class="fa fa-question fa-fw"></i> 常见问题</a></li><li><a class="vlts-menu fix-cursor-default" href="https://volantis.js.org/examples/" id="https:volantisjsorgexamples"><i class="fa fa-rss fa-fw"></i> 示例博客</a></li><li><a class="vlts-menu fix-cursor-default" href="https://volantis.js.org/contributors/" id="https:volantisjsorgcontributors"><i class="fa fa-fan fa-spin fa-fw"></i> 加入社区</a></li><hr><li><a class="vlts-menu fix-cursor-default" href="https://github.com/volantis-x/volantis-docs/" id="https:githubcomvolantis-xvolantis-docs"><i class="fa fa-code-branch fa-fw"></i> 本站源码</a></li><li><a class="vlts-menu fix-cursor-default" href="https://github.com/volantis-x/hexo-theme-volantis/" id="https:githubcomvolantis-xhexo-theme-volantis"><i class="fa fa-code-branch fa-fw"></i> 主题源码</a></li><hr><li><a class="vlts-menu fix-cursor-default" onclick='document.execCommand("print")'><i class="fa fa-print fa-fw"></i> 打印页面</a></li><hr><li><a class="vlts-menu fix-cursor-default toggle-mode-btn"><i class="fas fa-moon fa-fw"></i> Dark</a></li><hr><li class="music name"><p class="nav music-title fix-cursor-default"></p></li><li class="music ctrl"><a class="nav icon-only backward fix-cursor-default" onclick="aplayerBackward()"><i class="fa fa-step-backward fa-fw"></i></a><a class="nav icon-only toggle fix-cursor-default" onclick="aplayerToggle()"><i class="fa fa-play fa-fw"></i></a><a class="nav icon-only forward fix-cursor-default" onclick="aplayerForward()"><i class="fa fa-step-forward fa-fw"></i></a></li><li class="music volume"><a class="nav volume"><div class="aplayer-volume-bar-wrap"><div class="aplayer-volume-bar fix-cursor-pointer"><div class="aplayer-volume"></div><i class="left fa fa-volume-off fa-fw"></i><i class="right fa fa-volume-up fa-fw"></i></div></div></a></li></ul></div><script>function popMenu(e){var t=document.getElementById("rightmenu-wrapper"),n=document.getElementById("rightmenu-content"),l=document.documentElement.clientWidth||document.body.clientWidth,o=document.documentElement.clientHeight||document.body.clientHeight;t.style.left=e.clientX+"px",t.style.top=e.clientY+"px",t.style.display="block",2*e.clientX>l?n.classList.add("left"):n.classList.remove("left"),2*e.clientY>o?n.classList.add("top"):n.classList.remove("top");let c=document.getElementById("hr-text"),d=document.getElementById("hr-src"),y=document.getElementById("hr-href"),s=document.getElementById("menu-copy-src");null!=s&&(e.target.currentSrc?(s.style.display="block",s.addEventListener("click",(function(t){copyString(e.target.currentSrc)}),{once:!0}),d.style.display="block"):(s.style.display="none",d.style.display="none"));let r="";if(e.path)for(i=0;i<e.path.length;i++)null!=e.path[i].href&&e.path[i].href.length>0&&(r=e.path[i].href);let u=document.getElementById("menu-copy-text");u.style.display="none",c.style.display="none",0==r.length&&window.getSelection().toString()&&(u.style.display="block",c.style.display="block");let m=document.getElementById("menu-open-href");null!=m&&(r.length>0?(m.style.display="block",m.addEventListener("click",(function(e){window.open(r)}),{once:!0}),y.style.display="block"):(m.style.display="none",y.style.display="none"));let a=document.getElementById("menu-copy-href");return null!=a&&(r.length>0?(a.style.display="block",a.addEventListener("click",(function(e){copyString(r)}),{once:!0})):a.style.display="none"),volantis.APlayerLoaded&&checkAPlayer(),!1}function hideMenu(){document.getElementById("rightmenu-wrapper").style.display="none"}function copyString(e){const t=document.createElement("input");t.setAttribute("readonly","readonly"),document.body.appendChild(t),t.setAttribute("value",e),t.select(),document.execCommand("copy"),document.body.removeChild(t)}window.document.oncontextmenu=function(e){return!!e.ctrlKey||(!!/Android|webOS|BlackBerry/i.test(navigator.userAgent)||popMenu(e))},document.addEventListener("click",(function(e){document.getElementById("rightmenu-wrapper").style.display="none"})),document.execCommand("click")</script><script>function loadIssuesJS(){0!=$(".md").find(".issues-api").length&&loadScript("https://cdn.jsdelivr.net/npm/hexo-theme-volantis@4.3.1/source/js/issues.min.js")}$((function(){loadIssuesJS()})),volantis.pjax.push(()=>{"undefined"==typeof IssuesAPI&&loadIssuesJS()},"IssuesJS")</script><script defer="defer" src="https://cdn.jsdelivr.net/npm/vanilla-lazyload@17.1.0/dist/lazyload.min.js"></script><script>window.lazyLoadOptions={elements_selector:".lazyload",threshold:0},window.addEventListener("LazyLoad::Initialized",(function(n){window.lazyLoadInstance=n.detail.instance}),!1),document.addEventListener("DOMContentLoaded",(function(){lazyLoadInstance.update()})),document.addEventListener("pjax:complete",(function(){lazyLoadInstance.update()}))</script><script>window.FPConfig={delay:0,ignoreKeywords:[],maxRPS:5,hoverDelay:25}</script><script defer="defer" src="https://cdn.jsdelivr.net/gh/gijo-varghese/flying-pages@2.1.2/flying-pages.min.js"></script><script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script><script>var clipboard=new ClipboardJS(".btn-copy",{target:function(e){return e.nextElementSibling}});function wait(e,i){window.setTimeout(e,i)}function pjax_initCopyCode(){if($(".highlight .code pre").length+$(".article pre code").length!=0){var e="";e+='<button class="btn-copy" data-clipboard-snippet="">',e+='<i class="fas fa-copy"></i><span>COPY</span>',e+="</button>",$(".highlight .code pre").before(e),$(".article pre code").before(e),clipboard.off("success").on("success",(function(e){let i=$(e.trigger);i.addClass("copied");let a=$(i.find("i"));a.removeClass("fa-copy"),a.addClass("fa-check-circle");let n=$(i.find("span"));n[0].innerText="COPIED",wait((function(){a.removeClass("fa-check-circle"),a.addClass("fa-copy"),n[0].innerText="COPY"}),2e3)})),clipboard.off("error").on("error",(function(e){e.clearSelection();let i=$(e.trigger);i.addClass("copy-failed");let a=$(i.find("i"));a.removeClass("fa-copy"),a.addClass("fa-times-circle");let n=$(i.find("span"));n[0].innerText="COPY FAILED",wait((function(){a.removeClass("fa-times-circle"),a.addClass("fa-copy"),n[0].innerText="COPY"}),2e3)}))}}$((function(){pjax_initCopyCode()})),volantis.pjax.push(pjax_initCopyCode)</script><script type="text/javascript">function pjax_scrollrebeal(){ScrollReveal().reveal(".l_main .reveal",{distance:"32px",duration:"800",interval:"20",scale:"1",easing:"ease-out"})}loadScript("https://cdn.jsdelivr.net/npm/scrollreveal@4.0.6/dist/scrollreveal.min.js"),$((function(){var e=setInterval((function(){"block"==$("#safearea").css("display")&&"undefined"!=typeof ScrollReveal&&(clearInterval(e),pjax_scrollrebeal())}),100)})),volantis.pjax.push(pjax_scrollrebeal)</script><script>let APlayerController=new Object;APlayerController.id="5472211102",APlayerController.volume="0.7",loadCSS("https://cdn.jsdelivr.net/npm/aplayer@1.10/dist/APlayer.min.css",window.volantis.loadcss),loadScript("https://cdn.jsdelivr.net/npm/aplayer@1.10/dist/APlayer.min.js"),window.volantis.APlayerLoaded=0;var checkAPlayer=setInterval((function(){window.APlayer&&"block"==$("#safearea").css("display")&&(clearInterval(checkAPlayer),window.volantis.APlayerLoaded||window.MetingJSElement||(window.volantis.APlayerLoaded=1,loadScript("https://cdn.jsdelivr.net/npm/meting@2.0/dist/Meting.min.js")))}),2500);loadScript("https://cdn.jsdelivr.net/npm/hexo-theme-volantis@4.3.1/source/js/aplayer.min.js")</script><script src="https://cdn.jsdelivr.net/npm/hexo-theme-volantis@4.3.1/source/js/valine.min.js"></script><script>function emoji(i,e,a){return i+"/"+i+"-"+e+"."+a}for(var emojiMaps={},i=1;i<=54;i++)emojiMaps["tieba-"+i]=emoji("tieba",i,"png");for(i=1;i<=101;i++)emojiMaps["qq-"+i]=emoji("qq",i,"gif");for(i=1;i<=116;i++)emojiMaps["aru-"+i]=emoji("aru",i,"gif");for(i=1;i<=125;i++)emojiMaps["twemoji-"+i]=emoji("twemoji",i,"png");for(i=1;i<=4;i++)emojiMaps["weibo-"+i]=emoji("weibo",i,"png");function pjax_valine(){if(!document.querySelectorAll("#valine_container")[0])return;let i=pdata.commentPlaceholder||"快来评论吧~",e=pdata.commentPath;if(0==e.length){e=""||decodeURI(window.location.pathname)}(new Valine).init(Object.assign({path:null,placeholder:"快来评论吧~",appId:"eL9fCmXLl3nAe225XYo1cRxj-MdYXbMMI",appKey:"5uTd5Uu8WJJIej6Efrivsvaa",meta:["nick","mail","link"],requiredFields:["nick","mail"],enableQQ:!0,recordIP:!1,avatar:"robohash",pageSize:10,lang:"zh-cn",highlight:!0,mathJax:!1},{el:"#valine_container",path:e,placeholder:i,emojiCDN:"https://cdn.jsdelivr.net/gh/volantis-x/cdn-emoji/valine/",emojiMaps:emojiMaps}))}$((function(){pjax_valine()})),volantis.pjax.push(pjax_valine)</script><script defer="defer" src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-busuanzi@2.3/js/busuanzi.pure.mini.js" data-pjax></script><script src="https://cdn.jsdelivr.net/npm/hexo-theme-volantis@4.3.1/source/js/app.min.js"></script><script>const SearchServiceimagePath="https://cdn.jsdelivr.net/gh/volantis-x/cdn-volantis@master/img/",ROOT="/".endsWith("/")?"/":"//";function listenSearch(){customSearch=new HexoSearch({imagePath:SearchServiceimagePath})}function setSearchService(){listenSearch()}$(".input.u-search-input").one("focus",(function(){loadScript("https://cdn.jsdelivr.net/gh/volantis-x/cdn-volantis@2.6.4/js/search.js",setSearchService)}))</script><script src="https://cdn.jsdelivr.net/npm/node-waves@0.7.6/dist/waves.min.js"></script><script type="text/javascript">$((function(){Waves.attach(".flat-btn",["waves-button"]),Waves.attach(".float-btn",["waves-button","waves-float"]),Waves.attach(".float-btn-light",["waves-button","waves-float","waves-light"]),Waves.attach(".flat-box",["waves-block"]),Waves.attach(".float-box",["waves-block","waves-float"]),Waves.attach(".waves-image"),Waves.init()}))</script><script src="https://cdn.jsdelivr.net/gh/volantis-x/cdn-volantis@2/js/comment_typing.js"></script><script defer="defer">const LCCounter={app_id:"C2dIVXJ48qC7eHgvQRId6niR-MdYXbMMI",app_key:"1956OGJ4LQhDxheBAO5WhPJn",custom_api_server:"",getRecord:(e,t,r)=>new Promise((function(n,i){e("get","/classes/Counter?where="+encodeURIComponent(JSON.stringify({url:t}))).then(e=>e.json()).then(({results:o,code:s,error:a})=>{if(401===s)throw a;if(o&&o.length>0){var l=o[0];n(l)}else e("post","/classes/Counter",{url:t,title:r,times:0}).then(e=>e.json()).then((e,t)=>{if(t)throw t;n(e)}).catch(e=>{console.error("Failed to create",e),i(e)})}).catch(e=>{console.error("LeanCloud Counter Error:",e),i(e)})})),increment:(e,t)=>new Promise((function(r,n){e("post","/batch",{requests:t}).then(e=>{if((e=e.json()).error)throw e.error;r(e)}).catch(e=>{console.error("Failed to save visitor count",e),n(e)})})),buildIncrement:e=>({method:"PUT",path:"/1.1/classes/Counter/"+e,body:{times:{__op:"Increment",amount:1}}}),validUV(){var e="LeanCloudUVTimestamp",t=localStorage.getItem(e);return!(t&&(new Date).getTime()-parseInt(t)<=864e5)&&(localStorage.setItem(e,(new Date).getTime().toString()),!0)},addCount(e){var t=[],r=[],n=document.querySelector("#lc-sv"),o=this.getRecord(e,"http://aner1001.gitee.io/#lc-sv","Visits").then(e=>{r.push(this.buildIncrement(e.objectId));var t=document.querySelectorAll("#lc-sv #number");t.length>0&&t.forEach((t,r,i)=>{t.innerText=e.times+1,n&&(n.style.display="inline")})});t.push(o);var s=document.querySelector("#lc-uv"),a=this.getRecord(e,"http://aner1001.gitee.io/#lc-uv","Visitors").then(e=>{var t=this.validUV();t&&r.push(this.buildIncrement(e.objectId));var n=document.querySelectorAll("#lc-uv #number");n.length>0&&n.forEach((r,n,i)=>{r.innerText=e.times+(t?1:0),s&&(s.style.display="inline")})});t.push(a);var l=document.querySelectorAll("#lc-pv");for(l.length,i=0;i<l.length;i++){let n=l[i],o=n.getAttribute("data-title");var h="http://aner1001.gitee.io"+n.getAttribute("data-path");if(h){var c=this.getRecord(e,h,o).then(e=>{let t=window.location.pathname;if(t.includes("index.html")&&(t=t.substring(0,t.lastIndexOf("index.html"))),n.getAttribute("data-path")==t&&r.push(this.buildIncrement(e.objectId)),n){var i=n.querySelector("#lc-pv #number");i&&(n.getAttribute("data-path")==t?i.innerText=(e.times||0)+1:i.innerText=e.times||0,n.style.display="inline")}});t.push(c)}}Promise.all(t).then(()=>{r.length>0&&this.increment(e,r)})},fetchData(e){this.addCount((t,r,n)=>fetch(`${e}/1.1${r}`,{method:t,headers:{"X-LC-Id":this.app_id,"X-LC-Key":this.app_key,"Content-Type":"application/json"},body:JSON.stringify(n)}))},refreshCounter(){var e="-MdYXbMMI"!==this.app_id.slice(-9)?this.custom_api_server:`https://${this.app_id.slice(0,8).toLowerCase()}.api.lncldglobal.com`;e?this.fetchData(e):fetch("https://app-router.leancloud.cn/2/route?appId="+this.app_id).then(e=>e.json()).then(({api_server:e})=>{this.fetchData("https://"+e)})}};LCCounter.refreshCounter(),document.addEventListener("pjax:complete",(function(){LCCounter.refreshCounter()}))</script><script>const rootElement=document.documentElement,darkModeStorageKey="user-color-scheme",rootElementDarkModeAttributeName="data-user-color-scheme",setLS=(e,t)=>{localStorage.setItem(e,t)},removeLS=e=>{localStorage.removeItem(e)},getLS=e=>localStorage.getItem(e),getModeFromCSSMediaQuery=()=>window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light",resetRootDarkModeAttributeAndLS=()=>{var e;rootElement.removeAttribute("data-user-color-scheme"),e=darkModeStorageKey,localStorage.removeItem(e)},validColorModeKeys={dark:!0,light:!0},applyCustomDarkModeSettings=e=>{const t=e||getLS(darkModeStorageKey);t===getModeFromCSSMediaQuery()?resetRootDarkModeAttributeAndLS():validColorModeKeys[t]?rootElement.setAttribute("data-user-color-scheme",t):resetRootDarkModeAttributeAndLS()},invertDarkModeObj={dark:"light",light:"dark"},toggleCustomDarkMode=()=>{let e=getLS(darkModeStorageKey);if(validColorModeKeys[e])e=invertDarkModeObj[e];else{if(null!==e)return;e=invertDarkModeObj[getModeFromCSSMediaQuery()]}var t,o;return t=darkModeStorageKey,o=e,localStorage.setItem(t,o),e};var btn=$("#wrapper .toggle-mode-btn,#rightmenu-wrapper .toggle-mode-btn");function bindToggleButton(){btn.on("click",e=>{const t=toggleCustomDarkMode();applyCustomDarkModeSettings(t)})}applyCustomDarkModeSettings(),document.addEventListener("DOMContentLoaded",bindToggleButton),volantis.pjax.push(bindToggleButton),volantis.pjax.send(()=>{btn.unbind("click")},"toggle-mode-btn-unbind")</script><script>function listennSidebarTOC(){const e=document.querySelectorAll(".toc li");if(!e.length)return;const t=[...e].map(e=>{const t=e.querySelector(".toc-link"),n=document.getElementById(decodeURI(t.getAttribute("href")).replace("#",""));return t.addEventListener("click",e=>{e.preventDefault(),window.scrollTo({top:n.offsetTop+100,behavior:"smooth"})}),n});!function n(o){o=Math.floor(o+1e4);let r=new IntersectionObserver((r,c)=>{let i=document.documentElement.scrollHeight+100;if(i>o)return c.disconnect(),void n(i);let l=function(e){let n=0,o=e[n];if(o.boundingClientRect.top>0)return n=t.indexOf(o.target),0===n?0:n-1;for(;n<e.length;n++){if(!(e[n].boundingClientRect.top<=0))return t.indexOf(o.target);o=e[n]}return t.indexOf(o.target)}(r);!function(e){if(e.classList.contains("active-current"))return;document.querySelectorAll(".toc .active").forEach(e=>{e.classList.remove("active","active-current")}),e.classList.add("active","active-current");let t=e.parentNode;for(;!t.matches(".toc");)t.matches("li")&&t.classList.add("active"),t=t.parentNode}(e[l])},{rootMargin:o+"px 0px -100% 0px",threshold:0});t.forEach(e=>{e&&r.observe(e)})}(document.documentElement.scrollHeight)}document.addEventListener("DOMContentLoaded",listennSidebarTOC),document.addEventListener("pjax:success",listennSidebarTOC)</script><script>"serviceWorker"in navigator&&navigator.serviceWorker.register("/sw.js").then((function(e){e.onupdatefound=function(){var r=e.installing;r.onstatechange=function(){switch(r.state){case"installed":navigator.serviceWorker.controller?console.log("Updated serviceWorker."):console.log("serviceWorker Sucess!");break;case"redundant":console.log("The installing service worker became redundant.")}}}})).catch((function(e){console.log("Error during service worker registration:",e)}))</script><script src="https://cdn.jsdelivr.net/npm/pjax@0.2.8/pjax.min.js"></script><div class="pjax-animate"><script src="https://cdn.jsdelivr.net/npm/nprogress@0.2.0/nprogress.min.js"></script><div id="loading-bar-wrapper"><script>NProgress.configure({parent:"#loading-bar-wrapper",trickleSpeed:100})</script></div><script>window.ShowLoading=function(){NProgress.start()},window.HideLoading=function(){NProgress.done()}</script><script>volantis.pjax.push(window.HideLoading,"HideLoading"),volantis.pjax.send(window.ShowLoading,"ShowLoading"),volantis.pjax.error(window.HideLoading,"HideLoading")</script></div><script>var pjax;document.addEventListener("DOMContentLoaded",(function(){pjax=new Pjax({elements:'a[href]:not([href^="#"]):not([href="javascript:void(0)"]):not([pjax-fancybox])',selectors:["title","#pjax-container","#pjax-header-nav-list"],cacheBust:!1,timeout:5e3})})),document.addEventListener("pjax:send",(function(e){try{var n=window.location.pathname,t=e.triggerElement.href,o=[""];""!=o[0]&&o.forEach(e=>{-1==n.indexOf(e)&&-1==t.indexOf(e)||(window.location.href=t)})}catch(e){}window.subData=null,volantis.$switcher.removeClass("active"),volantis.$header.removeClass("z_search-open"),volantis.$wrapper.removeClass("sub"),volantis.$topBtn.unbind("click"),$(".menu a").unbind("click"),$(window).unbind("resize"),$(window).unbind("scroll"),$(document).unbind("scroll"),$(document).unbind("click"),$("body").unbind("click"),volantis.pjax.method.send.start()})),document.addEventListener("pjax:complete",(function(){$(".nav-main").find(".list-v").not(".menu-phone").removeAttr("style",""),$(".menu-phone.list-v").removeAttr("style",""),$("script[data-pjax], .pjax-reload script").each((function(){$(this).parent().append($(this).remove())}));try{volantis.pjax.method.complete.start()}catch(e){console.log(e)}})),document.addEventListener("pjax:error",(function(e){volantis.pjax.method.error.start(),window.location.href=e.triggerElement.href}))</script></div></body></html>